package com.jxpanda.infrastructure.crypto.algorithm.digest.contract;

import com.jxpanda.infrastructure.crypto.algorithm.Crypto;
import com.jxpanda.infrastructure.crypto.model.BinaryData;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


public interface Digest extends Crypto {

    default BinaryData digestFile(String filePath) {
        return digestFile(Path.of(filePath));
    }

    default BinaryData digestFile(Path file) {
        try (InputStream inputStream = Files.newInputStream(file)) {
            return digestFile(inputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    default BinaryData digestFile(InputStream inputStream) {
        MessageDigest messageDigest = createMessageDigest();
        try (DigestInputStream dis = new DigestInputStream(inputStream, messageDigest)) {
            // 仅读取，不需要处理返回值
            dis.transferTo(OutputStream.nullOutputStream());
            // 最终得到摘要 byte[]
            byte[] digestBytes = messageDigest.digest();
            return new BinaryData(digestBytes);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    default BinaryData digest(byte[] contentBytes) {
        return digest(new BinaryData(contentBytes));
    }

    default BinaryData digest(String contentString) {
        return digest(BinaryData.fromString(contentString));
    }

    default BinaryData digestFromBase64(String contentString) {
        return digest(BinaryData.fromBase64(contentString));
    }

    default BinaryData digest(BinaryData contentData) {
        byte[] digestBytes = createMessageDigest().digest(contentData.bytes());
        return new BinaryData(digestBytes);
    }

    default boolean check(byte[] contentBytes, String digest) {
        return digest(contentBytes).toHex().equalsIgnoreCase(digest);
    }

    default boolean check(String contentString, String digest) {
        return digest(contentString).toHex().equalsIgnoreCase(digest);
    }

    default boolean checkFile(String filePath, String digest) {
        return digestFile(filePath).toHex().equalsIgnoreCase(digest);
    }

    default boolean checkFile(Path file, String digest) {
        return digestFile(file).toHex().equalsIgnoreCase(digest);
    }

    default boolean checkFile(InputStream inputStream, String digest) {
        return digestFile(inputStream).toHex().equalsIgnoreCase(digest);
    }


    default MessageDigest createMessageDigest() {
        try {
            return MessageDigest.getInstance(getAlgorithm());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

}
